package com.hube.platform.tenant.configuration;

import com.codahale.metrics.MetricRegistry;
import com.hube.platform.tenant.constant.AppConstant;
import com.hube.platform.tenant.helper.FacadeBuilder;
import com.zaxxer.hikari.HikariDataSource;
import liquibase.integration.spring.SpringLiquibase;
import ma.glasnost.orika.MapperFacade;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@MapperScan({"com.hube.platform.tenant.mapper"})
@EnableTransactionManagement
public class DynamicDataSourceConfiguration {

    @Resource(name = "masterDataLiquibaseProperties")
    private LiquibaseProperties properties;

    private static MapperFacade facade = FacadeBuilder.mapperFactory.getMapperFacade();


    //    @Primary
    @Bean(AppConstant.MASTER_DB)
    @ConfigurationProperties(prefix = "spring.datasource.master-data")
    public DataSource master() {
        HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
//        hikariDataSource.setMetricRegistry(MetricRegistryBuilder.build(hikariDataSource.getPoolName()));
        hikariDataSource.setMetricRegistry(new MetricRegistry());
        return hikariDataSource;
    }

    @Primary
    @Bean(AppConstant.DYNAMIC_DATA_SOURCE)
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put(AppConstant.MASTER_DB, master());
        // 将 master 数据源作为默认指定的数据源
        dynamicDataSource.setDefaultTargetDataSource(master());
        // 其他数据源
        dynamicDataSource.setTargetDataSources(dataSourceMap);
        return dynamicDataSource;
    }

//    @Bean
//    public SqlSessionFactory getSqlSessionFactoryBean() throws Exception {
//        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
//        //获取mybatis-plus全局配置
//        GlobalConfig globalConfig = GlobalConfigUtils.defaults();
//        //mybatis-plus全局配置设置元数据对象处理器为自己实现的那个
//        globalConfig.setMetaObjectHandler(new MybatisMetaObjectHandler());
//        //配置数据源，此处配置为关键配置，如果没有将 dynamicDataSource作为数据源则不能实现切换
//        sqlSessionFactory.setDataSource(dynamicDataSource());
//        MybatisConfiguration configuration = new MybatisConfiguration();
//        configuration.setMapUnderscoreToCamelCase(true);
//        sqlSessionFactory.setConfiguration(configuration);
//        return sqlSessionFactory.getObject();
//    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        // 配置事务管理, 使用事务时在方法头部添加@Transactional注解即可
        return new DataSourceTransactionManager(dynamicDataSource());
    }

    @Bean
    public SpringLiquibase secondaryLiquibase() {
        //配置主数据源使用liquibase
        SpringLiquibase liquibase = facade.map(properties, SpringLiquibase.class);
        liquibase.setDataSource(master());
        liquibase.setShouldRun(properties.isEnabled());
        return liquibase;
    }

}